package org.springframework.core.type.classwriting;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.ServiceMethodMetadata;
import org.springframework.core.type.classreading.ImplementClassMetadataReadingVisitor;
import org.springframework.core.type.classreading.ImplementMethodMetadataReadingVisitor;
import org.springframework.core.type.classreading.ServiceClassMetadataReadingVisitor;
import org.springframework.util.MultiValueMap;

import cn.bonoon.kernel.support.entities.Persistable;
import cn.bonoon.kernel.support.services.ServiceSupport;


/**
 * <pre>
 * 实现接口，并且该接口部分已经实现了，只需要实现父类没有实现的方法
 * 在接口的方法上面和父类的方法上面定义的注释都应该被使用到
 * </pre>
 * @author jackson
 *
 */
public class ExtendsClassMetadataWriter extends AbstractMetadataWriter{
	private final ImplementClassMetadataReadingVisitor iVisitor;
	private final Set<String> annotationSet;
	private final List<ImplementMethodMetadataReadingVisitor> excludeMethods;
//	private final AutoImplements autoImplements;
	private final Class<?> parentClass;
	private final Class<? extends Persistable> entityClass;
	public ExtendsClassMetadataWriter(ImplementClassMetadataReadingVisitor iVisitor, ServiceClassMetadataReadingVisitor sVisitor, Class<?> siClass) throws Exception {
		super(sVisitor, siClass);
		this.annotationSet = new LinkedHashSet<String>(sVisitor.getAnnotationTypes());
		this.annotationSet.addAll(iVisitor.getAnnotationTypes());
		this.iVisitor = iVisitor;
		this.excludeMethods = new ArrayList<ImplementMethodMetadataReadingVisitor>();
		this.iVisitor.fillMethods(this.excludeMethods);
		
		this.parentClass = Class.forName(iVisitor.getClassName());
		this.entityClass = parseClass();
		
//		this.autoImplements = autoImplements;
	}
	
	@SuppressWarnings("unchecked")
	protected Class<? extends Persistable> parseClass(){
		Class<?> c = parentClass;
		do{
			Type t = c.getGenericSuperclass();
			if(t instanceof ParameterizedType){
				ParameterizedType genericSuperclass = (ParameterizedType)t;
				return (Class<? extends Persistable>) genericSuperclass.getActualTypeArguments()[0];
			}
			c = c.getSuperclass();
		}while(!ServiceSupport.class.equals(c));
		return null;
	}
	@Override
	protected boolean exclude(ServiceMethodMetadata smm) {
		for(ImplementMethodMetadataReadingVisitor immr : excludeMethods){
			if(immr.ckeck(smm)) return true;
		}
		return false;
	}
	
	@Override
	protected String parseClassName(){
		return iVisitor.getClassName();
	}
	
	@Override
	protected String parseParentName() {
		return iVisitor.getClassName();
	}
	
	//以下的注解，除了接口的定义还需要处理父类的定义
	@Override
	public Set<String> getAnnotationTypes() {
		return this.annotationSet;
	}

	@Override
	public Set<String> getMetaAnnotationTypes(String annotationType) {
		Set<String> mat = sVisitor.getMetaAnnotationTypes(annotationType);
		if(null == mat){
			mat = iVisitor.getMetaAnnotationTypes(annotationType);
		}
		return mat;
	}

	public boolean hasAnnotation(String annotationType) {
		return this.annotationSet.contains(annotationType);
	}

	@Override
	public boolean hasMetaAnnotation(String metaAnnotationType) {
		return sVisitor.hasMetaAnnotation(metaAnnotationType) || iVisitor.hasMetaAnnotation(metaAnnotationType);
	}

	@Override
	public boolean isAnnotated(String annotationType) {
		return sVisitor.isAnnotated(annotationType) || iVisitor.isAnnotated(annotationType);
	}
	
	@Override
	public AnnotationAttributes getAnnotationAttributes(String annotationType) {
		return getAnnotationAttributes(annotationType, false);
	}

	@Override
	public AnnotationAttributes getAnnotationAttributes(String annotationType, boolean classValuesAsString) {
		AnnotationAttributes raw = sVisitor.getAnnotationAttributes(annotationType, classValuesAsString);
		if(null == raw){
			raw = iVisitor.getAnnotationAttributes(annotationType, classValuesAsString);
		}
		return raw;
	}

	@Override
	public Set<MethodMetadata> getAnnotatedMethods(String annotationType) {
		Set<MethodMetadata> annotatedMethods = sVisitor.getAnnotatedMethods(annotationType);
		if(annotatedMethods.isEmpty()){
			annotatedMethods = iVisitor.getAnnotatedMethods(annotationType);
		}
		return annotatedMethods;
	}

	@Override
	public boolean hasAnnotatedMethods(String annotationType) {
		return sVisitor.hasAnnotatedMethods(annotationType) || iVisitor.hasAnnotatedMethods(annotationType);
	}

	@Override
	protected Class<? extends Persistable> parseEntityClass() throws Exception{
		return entityClass;
	}
	
	@Override
	protected Class<?> parseParentClass() throws Exception {
		return parentClass;
	}

	@Override
	public boolean isAnnotation() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public MultiValueMap<String, Object> getAllAnnotationAttributes(
			String annotationName) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public MultiValueMap<String, Object> getAllAnnotationAttributes(
			String annotationName, boolean classValuesAsString) {
		// TODO Auto-generated method stub
		return null;
	}
}
